#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
TrackVision - 智能目标跟踪轨迹分析系统
=====================================

作者：元歌
公司：广东润生软件
版本：1.0.0
日期：2024年

功能描述：
- 基于YOLOv8的实时目标检测与跟踪
- 智能轨迹分析和运动方向判断
- 实时统计信息显示和日志记录
- 支持多种目标类型：车辆、行人、摩托车等
- 自动生成catus.out日志文件

技术特点：
- 使用OpenCV进行视频处理
- 基于PIL的中文字体渲染
- 智能目标匹配算法
- 实时统计和数据分析
"""

import cv2
import numpy as np
from ultralytics import YOLO
import time
import math
from collections import defaultdict, deque
from PIL import Image, ImageDraw, ImageFont
import os
from datetime import datetime, timedelta

class SimpleCameraTracker:
    """
    智能目标跟踪器类
    
    作者：元歌
    公司：广东润生软件
    
    功能：
    - 实时目标检测与跟踪
    - 轨迹分析和运动方向判断
    - 统计信息计算和显示
    - 日志记录和文件输出
    """
    
    def __init__(self):
        # 初始化YOLO模型
        print("正在加载YOLO模型...")
        self.model = YOLO('yolov8n.pt')
        
        # 目标类别 - 增加更多车辆类型
        self.target_classes = ['person', 'car', 'motorcycle', 'bus', 'truck', 'bicycle', 'train']
        
        # 跟踪相关变量
        self.tracked_objects = {}
        self.next_id = 1
        self.trajectories = defaultdict(lambda: deque(maxlen=50))  # 增加轨迹长度
        self.velocities = defaultdict(lambda: deque(maxlen=10))  # 添加速度历史
        
        # 运动检测参数 - 降低阈值提高灵敏度
        self.movement_threshold = 3.0  # 降低移动阈值
        self.min_trajectory_length = 2  # 减少最小轨迹长度要求
        
        # 视频参数
        self.frame_width = 0
        self.frame_height = 0
        
        # 日志历史记录
        self.log_history = deque(maxlen=15)  # 保存最近15条日志记录
        self.static_objects = {}  # 静止物体记录
        self.static_check_interval = 30  # 静止物体检查间隔（帧数）
        
        # 日志频率控制
        self.last_log_times = {}  # 记录每个对象最后日志时间
        self.log_interval = 2.0  # 同一对象日志间隔（秒）
        self.last_frame_log_time = 0  # 上一帧日志时间
        
        # 统计信息
        self.start_time = time.time()  # 程序启动时间
        self.hourly_count = 0  # 每小时流动量
        self.daily_count = 0  # 当天流动量
        self.last_hour_reset = datetime.now().hour  # 上次重置小时计数的时间
        self.last_day_reset = datetime.now().date()  # 上次重置日计数的时间
        self.tracked_objects_count = 0  # 已跟踪对象总数
        
        # 日志文件
        self.log_file_path = "catus.out"
        self.init_log_file()
        
        # 尝试加载中文字体 - 使用适中的字体大小
        try:
            self.font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", 14)
            self.small_font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", 12)
            self.tiny_font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", 10)
        except:
            try:
                self.font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttf", 14)
                self.small_font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttf", 12)
                self.tiny_font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttf", 10)
            except:
                self.font = ImageFont.load_default()
                self.small_font = ImageFont.load_default()
                self.tiny_font = ImageFont.load_default()
                print("警告: 无法加载中文字体，将使用默认字体")
        
        # 类别中文映射
        self.class_chinese = {
            'person': '行人',
            'car': '汽车',
            'motorcycle': '摩托车',
            'bus': '公交车',
            'truck': '卡车',
            'bicycle': '自行车',
            'train': '火车'
        }
        
        print("模型加载完成！")
    
    def init_log_file(self):
        """
        初始化日志文件
        
        作者：元歌
        公司：广东润生软件
        
        功能：创建catus.out日志文件并写入启动信息
        """
        try:
            with open(self.log_file_path, 'a', encoding='utf-8') as f:
                f.write(f"\n=== 程序启动 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ===\n")
        except Exception as e:
            print(f"警告: 无法创建日志文件: {e}")
    
    def write_to_log_file(self, log_text):
        """
        写入日志到文件
        
        作者：元歌
        公司：广东润生软件
        
        功能：将日志信息写入catus.out文件
        参数：log_text - 要写入的日志文本
        """
        try:
            with open(self.log_file_path, 'a', encoding='utf-8') as f:
                f.write(f"{log_text}\n")
        except Exception as e:
            print(f"警告: 无法写入日志文件: {e}")
    
    def update_statistics(self):
        """
        更新统计信息
        
        作者：元歌
        公司：广东润生软件
        
        功能：更新每小时和每天的流动量统计
        """
        current_time = datetime.now()
        
        # 检查是否需要重置小时计数
        if current_time.hour != self.last_hour_reset:
            self.hourly_count = 0
            self.last_hour_reset = current_time.hour
        
        # 检查是否需要重置日计数
        if current_time.date() != self.last_day_reset:
            self.daily_count = 0
            self.last_day_reset = current_time.date()
    
    def get_runtime(self):
        """
        获取运行时间
        
        作者：元歌
        公司：广东润生软件
        
        功能：计算程序运行的总时间
        返回：格式化的运行时间字符串 (HH:MM:SS)
        """
        runtime_seconds = int(time.time() - self.start_time)
        hours = runtime_seconds // 3600
        minutes = (runtime_seconds % 3600) // 60
        seconds = runtime_seconds % 60
        return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
    
    def draw_chinese_text(self, img, text, position, font, color=(255, 255, 255)):
        """
        在图像上绘制中文文字
        
        作者：元歌
        公司：广东润生软件
        
        功能：使用PIL在OpenCV图像上绘制中文文字
        参数：
        - img: 输入图像
        - text: 要绘制的文字
        - position: 绘制位置 (x, y)
        - font: 字体对象
        - color: 文字颜色 (BGR格式)
        返回：绘制文字后的图像
        """
        img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        draw = ImageDraw.Draw(img_pil)
        draw.text(position, text, font=font, fill=color)
        img_cv = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
        return img_cv
    
    def should_log(self, obj_id, log_type):
        """判断是否应该记录日志（控制频率）"""
        current_time = time.time()
        
        # 特殊日志类型总是记录
        if log_type in ["discovered", "lost", "static"]:
            return True
        
        # 检查同一对象的日志间隔
        if obj_id in self.last_log_times:
            if current_time - self.last_log_times[obj_id] < self.log_interval:
                return False
        
        # 检查全局日志频率（每0.5秒最多一条）
        if current_time - self.last_frame_log_time < 0.5:
            return False
        
        return True
    
    def add_log_entry(self, obj_id, obj_data, log_type="tracking"):
        """添加日志条目到历史记录"""
        # 检查是否应该记录日志
        if not self.should_log(obj_id, log_type):
            return
        
        velocity = self.calculate_velocity(self.trajectories[obj_id])
        direction = self.get_movement_direction(self.trajectories[obj_id])
        class_name = self.class_chinese.get(obj_data['class'], obj_data['class'])
        current_time = time.strftime("%H:%M:%S", time.localtime())
        
        # 计算到右边界的距离
        bbox = obj_data['bbox']
        distance_to_right = self.frame_width - bbox[2]
        
        # 预测消失时间
        time_to_disappear = distance_to_right / velocity if velocity > 0 else float('inf')
        
        if log_type == "discovered":
            log_text = f"[{current_time}] 发现目标 ID:{obj_id} {class_name} 方向:{direction} 速度:{velocity:.1f}px/s 预计:{time_to_disappear:.1f}秒"
        elif log_type == "lost":
            log_text = f"[{current_time}] 目标丢失 ID:{obj_id} {class_name}"
        elif log_type == "static":
            log_text = f"[{current_time}] 静止目标 ID:{obj_id} {class_name} 速度:{velocity:.1f}px/s 保留跟踪"
        elif log_type == "left_movement":
            log_text = f"[{current_time}] 向左移动 ID:{obj_id} {class_name} 速度:{velocity:.1f}px/s"
        else:
            log_text = f"[{current_time}] 跟踪中 ID:{obj_id} {class_name} {direction} {velocity:.1f}px/s"
        
        log_entry = {
            'time': current_time,
            'text': log_text,
            'type': log_type
        }
        
        self.log_history.append(log_entry)
        
        # 写入日志到文件
        self.write_to_log_file(log_text)
        
        # 更新统计信息
        if log_type == "discovered":
            self.tracked_objects_count += 1
            self.hourly_count += 1
            self.daily_count += 1
        
        # 更新日志时间记录
        self.last_log_times[obj_id] = time.time()
        self.last_frame_log_time = time.time()
    
    def calculate_velocity(self, trajectory):
        """计算速度"""
        if len(trajectory) < 2:
            return 0
        
        recent_points = list(trajectory)[-min(5, len(trajectory)):]
        if len(recent_points) < 2:
            return 0
            
        start_point = recent_points[0]
        end_point = recent_points[-1]
        
        # 计算水平距离
        horizontal_distance = abs(end_point[0] - start_point[0])
        time_elapsed = len(recent_points) / 30  # 假设30fps
        
        if time_elapsed == 0:
            return 0
            
        velocity = horizontal_distance / time_elapsed
        return velocity
    
    def is_moving_right(self, trajectory):
        """判断是否向右移动 - 优化算法提高检测灵敏度"""
        if len(trajectory) < self.min_trajectory_length:
            return False
            
        recent_points = list(trajectory)[-min(5, len(trajectory)):]
        if len(recent_points) < 2:
            return False
        
        # 使用滑动窗口检测连续移动
        total_horizontal_movement = 0
        movement_count = 0
        
        for i in range(1, len(recent_points)):
            horizontal_diff = recent_points[i][0] - recent_points[i-1][0]
            if abs(horizontal_diff) > 1:  # 忽略微小抖动
                total_horizontal_movement += horizontal_diff
                movement_count += 1
        
        if movement_count == 0:
            return False
            
        # 计算平均移动方向
        avg_movement = total_horizontal_movement / movement_count
        
        # 降低水平移动阈值，提高灵敏度
        return avg_movement > self.movement_threshold
    
    def get_movement_direction(self, trajectory):
        """获取移动方向 - 只判断左右，忽略上下"""
        if len(trajectory) < 2:
            return "静止"
            
        recent_points = list(trajectory)[-min(5, len(trajectory)):]
        if len(recent_points) < 2:
            return "静止"
        
        # 计算连续的水平移动
        total_horizontal_movement = 0
        movement_count = 0
        
        for i in range(1, len(recent_points)):
            horizontal_diff = recent_points[i][0] - recent_points[i-1][0]
            if abs(horizontal_diff) > 1:  # 忽略微小抖动
                total_horizontal_movement += horizontal_diff
                movement_count += 1
        
        if movement_count == 0:
            return "静止"
            
        # 计算平均移动方向
        avg_movement = total_horizontal_movement / movement_count
        
        # 降低水平移动阈值，提高灵敏度
        if abs(avg_movement) < 2:  # 进一步降低阈值
            return "静止"
        elif avg_movement > 0:
            return "向右"
        else:
            return "向左"
    
    def is_moving_slowly(self, trajectory):
        """判断是否移动缓慢（静止）"""
        velocity = self.calculate_velocity(trajectory)
        return velocity < 5.0  # 速度小于5像素/秒认为是静止
    
    def calculate_matching_score(self, detection, tracked_obj, obj_id):
        """计算检测结果与跟踪对象的匹配分数"""
        x1, y1, x2, y2 = detection['bbox']
        center_x = (x1 + x2) / 2
        center_y = (y1 + y2) / 2
        
        last_center = tracked_obj['last_center']
        
        # 计算距离
        horizontal_distance = abs(center_x - last_center[0])
        vertical_distance = abs(center_y - last_center[1])
        total_distance = math.sqrt(horizontal_distance**2 + vertical_distance**2)
        
        # 计算尺寸相似度
        current_size = (x2 - x1) * (y2 - y1)
        last_bbox = tracked_obj['bbox']
        last_size = (last_bbox[2] - last_bbox[0]) * (last_bbox[3] - last_bbox[1])
        size_ratio = min(current_size, last_size) / max(current_size, last_size) if max(current_size, last_size) > 0 else 0
        
        # 计算速度一致性
        velocity_consistency = 1.0
        if obj_id in self.velocities and len(self.velocities[obj_id]) > 0:
            expected_x = last_center[0] + np.mean(list(self.velocities[obj_id])) * 0.033  # 假设30fps
            velocity_consistency = max(0, 1.0 - abs(center_x - expected_x) / 50)
        
        # 综合评分：距离权重0.5，尺寸权重0.3，速度权重0.2
        distance_score = max(0, 1.0 - total_distance / 100)
        size_score = size_ratio
        velocity_score = velocity_consistency
        
        total_score = distance_score * 0.5 + size_score * 0.3 + velocity_score * 0.2
        
        return total_score, total_distance
    
    def update_tracking(self, detections, frame_count):
        """更新跟踪 - 使用更稳定的匹配算法"""
        current_objects = {}
        used_detections = set()
        
        # 为每个跟踪对象寻找最佳匹配
        for obj_id, obj_data in self.tracked_objects.items():
            best_match_idx = None
            best_score = 0
            best_distance = float('inf')
            
            for i, detection in enumerate(detections):
                if i in used_detections:
                    continue
                    
                if detection['class'] != obj_data['class']:
                    continue
                
                score, distance = self.calculate_matching_score(detection, obj_data, obj_id)
                
                # 要求最小匹配分数和最大距离
                if score > best_score and score > 0.3 and distance < 120:
                    best_score = score
                    best_distance = distance
                    best_match_idx = i
            
            # 更新匹配的对象
            if best_match_idx is not None:
                detection = detections[best_match_idx]
                used_detections.add(best_match_idx)
                
                x1, y1, x2, y2 = detection['bbox']
                center_x = (x1 + x2) / 2
                center_y = (y1 + y2) / 2
                
                # 更新对象信息
                obj_data['last_center'] = (center_x, center_y)
                obj_data['bbox'] = (x1, y1, x2, y2)
                obj_data['confidence'] = detection['confidence']
                obj_data['last_seen'] = time.time()
                
                # 添加到轨迹
                self.trajectories[obj_id].append((center_x, center_y))
                
                # 计算速度
                velocity = self.calculate_velocity(self.trajectories[obj_id])
                self.velocities[obj_id].append(velocity)
                
                # 判断移动方向和状态
                direction = self.get_movement_direction(self.trajectories[obj_id])
                is_moving_right = direction == "向右"
                is_moving_left = direction == "向左"
                is_static = self.is_moving_slowly(self.trajectories[obj_id])
                
                obj_data['is_moving_right'] = is_moving_right
                obj_data['is_moving_left'] = is_moving_left
                obj_data['is_static'] = is_static
                obj_data['direction'] = direction
                
                # 记录日志 - 优化频率控制
                if is_moving_left:
                    # 向左移动的日志频率更低
                    if obj_id not in self.last_log_times or time.time() - self.last_log_times[obj_id] > 3.0:
                        self.add_log_entry(obj_id, obj_data, "left_movement")
                elif is_static and obj_id not in self.static_objects:
                    self.add_log_entry(obj_id, obj_data, "static")
                    self.static_objects[obj_id] = {
                        'data': obj_data,
                        'last_check': frame_count,
                        'check_count': 0
                    }
                elif is_moving_right and obj_id not in self.static_objects:
                    self.add_log_entry(obj_id, obj_data, "discovered")
                
                current_objects[obj_id] = obj_data
        
        # 为未匹配的检测创建新对象
        for i, detection in enumerate(detections):
            if i in used_detections:
                continue
                
            if detection['class'] not in self.target_classes:
                continue
                
            x1, y1, x2, y2 = detection['bbox']
            center_x = (x1 + x2) / 2
            center_y = (y1 + y2) / 2
            
            obj_id = self.next_id
            self.next_id += 1
            
            self.tracked_objects[obj_id] = {
                'class': detection['class'],
                'last_center': (center_x, center_y),
                'bbox': (x1, y1, x2, y2),
                'confidence': detection['confidence'],
                'last_seen': time.time(),
                'is_moving_right': False,
                'is_moving_left': False,
                'is_static': False,
                'direction': "静止"
            }
            
            self.trajectories[obj_id].append((center_x, center_y))
            self.velocities[obj_id].append(0)
            
            current_objects[obj_id] = self.tracked_objects[obj_id]
        
        # 检查静止物体
        self.check_static_objects(frame_count)
        
        # 清理长时间未见的对象
        current_time = time.time()
        to_remove = []
        for obj_id, obj_data in self.tracked_objects.items():
            if current_time - obj_data['last_seen'] > 2.5:  # 稍微缩短清理时间
                # 记录目标丢失日志
                self.add_log_entry(obj_id, obj_data, "lost")
                to_remove.append(obj_id)
        
        for obj_id in to_remove:
            del self.tracked_objects[obj_id]
            if obj_id in self.trajectories:
                del self.trajectories[obj_id]
            if obj_id in self.velocities:
                del self.velocities[obj_id]
            if obj_id in self.static_objects:
                del self.static_objects[obj_id]
        
        return current_objects
    
    def check_static_objects(self, frame_count):
        """检查静止物体是否重新开始移动"""
        to_remove_from_static = []
        
        for obj_id, static_info in self.static_objects.items():
            if frame_count - static_info['last_check'] >= self.static_check_interval:
                static_info['check_count'] += 1
                static_info['last_check'] = frame_count
                
                # 检查是否重新开始移动
                if obj_id in self.trajectories and len(self.trajectories[obj_id]) > 5:
                    direction = self.get_movement_direction(self.trajectories[obj_id])
                    velocity = self.calculate_velocity(self.trajectories[obj_id])
                    
                    if direction != "静止" and velocity > 5.0:
                        # 重新开始移动，从静止列表中移除
                        to_remove_from_static.append(obj_id)
                        if direction == "向右":
                            # 更新对象数据
                            static_info['data']['is_moving_right'] = True
                            static_info['data']['direction'] = direction
                            self.add_log_entry(obj_id, static_info['data'], "discovered")
        
        # 移除重新移动的物体
        for obj_id in to_remove_from_static:
            del self.static_objects[obj_id]
    
    def draw_tracking_info(self, frame, tracked_objects):
        """绘制跟踪信息"""
        for obj_id, obj_data in tracked_objects.items():
            if not obj_data['is_moving_right']:
                continue
                
            bbox = obj_data['bbox']
            x1, y1, x2, y2 = map(int, bbox)
            
            # 绘制边界框
            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
            
            # 绘制轨迹
            if obj_id in self.trajectories:
                trajectory = list(self.trajectories[obj_id])
                for i in range(1, len(trajectory)):
                    pt1 = (int(trajectory[i-1][0]), int(trajectory[i-1][1]))
                    pt2 = (int(trajectory[i][0]), int(trajectory[i][1]))
                    cv2.line(frame, pt1, pt2, (0, 255, 0), 2)
            
            # 绘制ID和类别
            velocity = self.calculate_velocity(self.trajectories[obj_id])
            class_name = self.class_chinese.get(obj_data['class'], obj_data['class'])
            label = f"ID:{obj_id} {class_name} 速度:{velocity:.1f}px/s"
            frame = self.draw_chinese_text(frame, label, (x1, y1-30), self.small_font, (0, 255, 0))
        
        return frame
    
    def draw_statistics_panel(self, frame):
        """在视频右上角绘制统计信息面板"""
        # 更新统计信息
        self.update_statistics()
        
        # 获取统计信息
        runtime = self.get_runtime()
        current_time = datetime.now().strftime("%H:%M:%S")
        
        # 绘制统计信息 - 直接显示在右上角
        text_x = frame.shape[1] - 20  # 靠右对齐
        y_offset = 20  # 往上移动
        
        # 运行时间
        frame = self.draw_chinese_text(frame, f"运行时间: {runtime}", (text_x - 120, y_offset), self.small_font, (0, 255, 0))
        y_offset += 25
        
        # 当前时间
        frame = self.draw_chinese_text(frame, f"当前时间: {current_time}", (text_x - 120, y_offset), self.small_font, (0, 255, 0))
        y_offset += 25
        
        # 每小时流动量
        frame = self.draw_chinese_text(frame, f"每小时流动量: {self.hourly_count}", (text_x - 120, y_offset), self.small_font, (255, 255, 0))
        y_offset += 25
        
        # 当天流动量
        frame = self.draw_chinese_text(frame, f"当天流动量: {self.daily_count}", (text_x - 120, y_offset), self.small_font, (255, 165, 0))
        
        return frame
    
    def draw_log_panel(self, frame, tracked_objects):
        """绘制跟踪日志面板"""
        log_height = 280  # 进一步增加日志面板高度
        log_width = frame.shape[1]
        
        # 创建半透明背景
        log_panel = np.zeros((log_height, log_width, 3), dtype=np.uint8)
        log_panel[:] = (0, 0, 0)
        
        # 添加标题
        log_panel = self.draw_chinese_text(log_panel, "实时跟踪日志", (10, 10), self.font, (255, 255, 255))
        
        # 添加分隔线
        cv2.line(log_panel, (10, 35), (log_width-10, 35), (255, 255, 255), 1)
        
        # 显示历史日志记录 - 使用新的日志格式，增加显示数量
        y_offset = 50
        log_count = 0
        max_logs = 12  # 最多显示12条日志
        
        for log_entry in reversed(list(self.log_history)):
            if y_offset > log_height - 20 or log_count >= max_logs:
                break
                
            # 根据日志类型设置颜色
            if log_entry['type'] == "discovered":
                color = (0, 255, 0)  # 绿色 - 发现目标
            elif log_entry['type'] == "lost":
                color = (0, 0, 255)  # 红色 - 目标丢失
            elif log_entry['type'] == "static":
                color = (255, 255, 0)  # 黄色 - 静止目标
            elif log_entry['type'] == "left_movement":
                color = (255, 165, 0)  # 橙色 - 向左移动
            else:
                color = (255, 255, 255)  # 白色 - 普通跟踪
            
            # 截断过长的日志文本 - 根据分辨率调整
            display_text = log_entry['text']
            max_length = min(150, log_width // 8)  # 根据界面宽度动态调整
            if len(display_text) > max_length:
                display_text = display_text[:max_length-3] + "..."
            
            log_panel = self.draw_chinese_text(log_panel, display_text, (10, y_offset), self.small_font, color)
            y_offset += 20  # 增加行间距
            log_count += 1
        
        # 显示当前跟踪的对象
        if tracked_objects:
            current_text = "当前跟踪对象:"
            log_panel = self.draw_chinese_text(log_panel, current_text, (10, y_offset), self.small_font, (0, 255, 0))
            y_offset += 20
            
            for obj_id, obj_data in tracked_objects.items():
                if y_offset > log_height - 20:
                    break
                    
                velocity = self.calculate_velocity(self.trajectories[obj_id])
                direction = obj_data.get('direction', '静止')
                class_name = self.class_chinese.get(obj_data['class'], obj_data['class'])
                
                current_log = f"ID:{obj_id} {class_name} {direction} 速度:{velocity:.1f}px/s"
                log_panel = self.draw_chinese_text(log_panel, current_log, (10, y_offset), self.small_font, (0, 255, 0))
                y_offset += 20
        
        # 将日志面板添加到帧底部
        result_frame = np.vstack([frame, log_panel])
        return result_frame
    
    def run_camera(self):
        """运行摄像头实时跟踪"""
        # 打开摄像头
        cap = cv2.VideoCapture(0)
        
        if not cap.isOpened():
            print("无法打开摄像头，请检查摄像头连接")
            return
        
        # 设置摄像头分辨率 - 尝试更宽的分辨率
        resolutions = [
            (2560, 1440),  # 2K分辨率
            (1920, 1080),  # Full HD
            (1600, 900),   # 中等分辨率
            (1280, 720)    # 标准分辨率
        ]
        
        actual_width = 0
        actual_height = 0
        
        for width, height in resolutions:
            cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
            cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
            actual_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            actual_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            
            if actual_width >= width * 0.8:  # 如果达到目标分辨率的80%以上
                break
        
        self.frame_width = actual_width
        self.frame_height = actual_height
        
        print(f"摄像头分辨率: {self.frame_width}x{self.frame_height}")
        print("按 'q' 键退出程序")
        
        frame_count = 0
        while True:
            ret, frame = cap.read()
            if not ret:
                break
            
            frame_count += 1
            
            # YOLO检测 - 降低置信度阈值提高检测率
            results = self.model(frame, 
                               conf=0.3,  # 降低置信度阈值，检测更多目标
                               iou=0.4,   # 非极大值抑制阈值
                               verbose=False)
            
            # 解析检测结果
            detections = []
            for result in results:
                boxes = result.boxes
                if boxes is not None:
                    for i in range(len(boxes)):
                        x1, y1, x2, y2 = boxes.xyxy[i].cpu().numpy()
                        confidence = boxes.conf[i].cpu().numpy()
                        class_id = int(boxes.cls[i].cpu().numpy())
                        class_name = self.model.names[class_id]
                        
                        detections.append({
                            'bbox': (x1, y1, x2, y2),
                            'confidence': confidence,
                            'class': class_name
                        })
            
            # 更新跟踪
            tracked_objects = self.update_tracking(detections, frame_count)
            
            # 绘制跟踪信息
            frame = self.draw_tracking_info(frame, tracked_objects)
            
            # 绘制统计信息面板
            frame = self.draw_statistics_panel(frame)
            
            # 绘制日志面板
            frame = self.draw_log_panel(frame, tracked_objects)
            
            # 显示帧
            cv2.imshow('TrackVision - Intelligent Target Tracking System', frame)
            
            # 按'q'退出
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        
        # 清理资源
        cap.release()
        cv2.destroyAllWindows()

def main():
    """
    主函数
    
    作者：元歌
    公司：广东润生软件
    
    功能：程序入口点，初始化跟踪器并启动摄像头跟踪
    """
    print("=" * 50)
    print("TrackVision - Intelligent Target Tracking System")
    print("=" * 50)
    
    tracker = SimpleCameraTracker()
    tracker.run_camera()

if __name__ == "__main__":
    main()
